from fastapi import APIRouter, Depends, HTTPException, Query, Path
from sqlalchemy.orm import Session
from typing import Optional, List, Dict, Any
import logging

from database import get_db
from schemas import (
    SchedulingStrategyCreate,
    SchedulingStrategyUpdate,
    SchedulingStrategyResponse,
    GenericResponse,
    DataResponse,
    ListResponse
)
from services.scheduling_service import SchedulingService
from exceptions import NotFoundException, ValidationException, BaseCustomException
from response_utils import list_response

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

router = APIRouter(prefix="/api/v1", tags=["调度策略管理"])


@router.post("/strategies", response_model=DataResponse[SchedulingStrategyResponse], summary="创建调度策略")
async def create_strategy(
    strategy_data: SchedulingStrategyCreate,
    db: Session = Depends(get_db)
):
    """
    创建新的调度策略
    
    - **name**: 策略名称
    - **description**: 策略描述
    - **type**: 策略类型 (priority_based, load_balanced, resource_optimized等)
    - **scenario**: 应用场景
    - **status**: 策略状态 (draft, active, paused, deprecated)
    - **priority**: 优先级 (数字越小优先级越高)
    - **max_concurrent_tasks**: 最大并发任务数
    - **cloud_nodes**: 云端节点数
    - **edge_nodes**: 边缘节点数
    - **config**: 策略配置
    - **metrics**: 性能指标
    """
    try:
        service = SchedulingService(db)
        strategy = service.create_strategy(strategy_data)
        
        logger.info(f"创建调度策略成功: {strategy.strategy_id}")
        
        return DataResponse(
            success=True,
            message=f"调度策略 '{strategy.name}' 创建成功",
            data=strategy
        )
        
    except ValidationException as e:
        logger.warning(f"创建调度策略验证失败: {str(e)}")
        raise HTTPException(status_code=422, detail=str(e))
    except BaseCustomException as e:
        logger.error(f"创建调度策略业务逻辑错误: {str(e)}")
        raise HTTPException(status_code=500, detail=str(e))
    except Exception as e:
        logger.error(f"创建调度策略未知错误: {str(e)}")
        raise HTTPException(status_code=500, detail=f"创建调度策略失败: {str(e)}")


@router.get("/strategies", response_model=ListResponse[SchedulingStrategyResponse], summary="获取调度策略列表")
async def get_strategies(
    page: int = 1,
    page_size: int = 20,
    # 过滤参数
    status: Optional[str] = Query(None, description="状态过滤 (draft, active, paused, deprecated)"),
    type: Optional[str] = Query(None, description="类型过滤"),
    scenario: Optional[str] = Query(None, description="场景过滤"),
    search: Optional[str] = Query(None, description="搜索关键词"),
    # 排序参数
    sort_by: str = Query("created_at", description="排序字段"),
    sort_order: str = Query("desc", description="排序顺序 (asc, desc)"),
    db: Session = Depends(get_db)
):
    """
    获取调度策略列表
    
    支持分页、过滤、搜索和排序功能
    """
    try:
        service = SchedulingService(db)
        
        strategies, total_count = service.get_strategies(
            page=page,
            page_size=page_size,
            status_filter=status,
            type_filter=type,
            scenario_filter=scenario,
            search_term=search,
            sort_by=sort_by,
            sort_order=sort_order
        )
        
        # 创建分页信息
        from response_utils import create_pagination_info
        pagination = create_pagination_info(page, page_size, total_count)
        
        # 调用服务层的统计方法
        summary = service.get_statistics()
        
        logger.info(f"获取调度策略列表成功: 共{total_count}条记录")
        
        return list_response(
            items=strategies,
            total_count=total_count,
            pagination=pagination,
            summary=summary,
            message="获取调度策略列表成功"
        )
        
    except ValidationException as e:
        logger.warning(f"获取调度策略列表验证失败: {str(e)}")
        raise HTTPException(status_code=422, detail=str(e))
    except BaseCustomException as e:
        logger.error(f"获取调度策略列表业务逻辑错误: {str(e)}")
        raise HTTPException(status_code=500, detail=str(e))
    except Exception as e:
        logger.error(f"获取调度策略列表未知错误: {str(e)}")
        raise HTTPException(status_code=500, detail=f"获取调度策略列表失败: {str(e)}")


@router.get("/strategies/{strategy_id}", response_model=DataResponse[SchedulingStrategyResponse], summary="获取调度策略详情")
async def get_strategy(
    strategy_id: str = Path(..., description="策略ID"),
    db: Session = Depends(get_db)
):
    """
    根据ID获取调度策略详情
    """
    try:
        service = SchedulingService(db)
        strategy = service.get_strategy_by_id(strategy_id)
        
        logger.info(f"获取调度策略详情成功: {strategy_id}")
        
        return DataResponse(
            success=True,
            message="获取调度策略详情成功",
            data=strategy
        )
        
    except NotFoundException as e:
        logger.warning(f"调度策略不存在: {strategy_id}")
        raise HTTPException(status_code=404, detail=str(e))
    except Exception as e:
        logger.error(f"获取调度策略详情未知错误: {str(e)}")
        raise HTTPException(status_code=500, detail=f"获取调度策略详情失败: {str(e)}")


@router.put("/strategies/{strategy_id}", response_model=DataResponse[SchedulingStrategyResponse], summary="更新调度策略")
async def update_strategy(
    update_data: SchedulingStrategyUpdate,
    strategy_id: str = Path(..., description="策略ID"),
    db: Session = Depends(get_db)
):
    """
    更新调度策略
    
    可以部分更新，只需要提供需要更新的字段
    """
    try:
        service = SchedulingService(db)
        strategy = service.update_strategy(strategy_id, update_data)
        
        logger.info(f"更新调度策略成功: {strategy_id}")
        
        return DataResponse(
            success=True,
            message=f"调度策略 '{strategy.name}' 更新成功",
            data=strategy
        )
        
    except NotFoundException as e:
        logger.warning(f"调度策略不存在: {strategy_id}")
        raise HTTPException(status_code=404, detail=str(e))
    except ValidationException as e:
        logger.warning(f"更新调度策略验证失败: {str(e)}")
        raise HTTPException(status_code=422, detail=str(e))
    except BaseCustomException as e:
        logger.error(f"更新调度策略业务逻辑错误: {str(e)}")
        raise HTTPException(status_code=500, detail=str(e))
    except Exception as e:
        logger.error(f"更新调度策略未知错误: {str(e)}")
        raise HTTPException(status_code=500, detail=f"更新调度策略失败: {str(e)}")


@router.delete("/strategies/{strategy_id}", response_model=GenericResponse, summary="删除调度策略")
async def delete_strategy(
    strategy_id: str = Path(..., description="策略ID"),
    db: Session = Depends(get_db)
):
    """
    删除调度策略
    """
    try:
        service = SchedulingService(db)
        success = service.delete_strategy(strategy_id)
        
        if success:
            logger.info(f"删除调度策略成功: {strategy_id}")
            return GenericResponse(
                success=True,
                message=f"调度策略 {strategy_id} 删除成功"
            )
        else:
            raise HTTPException(status_code=500, detail="删除调度策略失败")
        
    except NotFoundException as e:
        logger.warning(f"调度策略不存在: {strategy_id}")
        raise HTTPException(status_code=404, detail=str(e))
    except BaseCustomException as e:
        logger.error(f"删除调度策略业务逻辑错误: {str(e)}")
        raise HTTPException(status_code=500, detail=str(e))
    except Exception as e:
        logger.error(f"删除调度策略未知错误: {str(e)}")
        raise HTTPException(status_code=500, detail=f"删除调度策略失败: {str(e)}")


@router.post("/strategies/{strategy_id}/execute", response_model=DataResponse[Dict[str, Any]], summary="执行调度策略")
async def execute_strategy(
    strategy_id: str = Path(..., description="策略ID"),
    db: Session = Depends(get_db)
):
    """
    执行指定的调度策略
    
    只有状态为 'active' 的策略才能被执行
    """
    try:
        service = SchedulingService(db)
        result = service.execute_strategy(strategy_id)
        
        logger.info(f"执行调度策略成功: {strategy_id}")
        
        return DataResponse(
            success=True,
            message=f"调度策略 {strategy_id} 执行成功",
            data=result
        )
        
    except NotFoundException as e:
        logger.warning(f"调度策略不存在: {strategy_id}")
        raise HTTPException(status_code=404, detail=str(e))
    except ValidationException as e:
        logger.warning(f"执行调度策略验证失败: {str(e)}")
        raise HTTPException(status_code=422, detail=str(e))
    except BaseCustomException as e:
        logger.error(f"执行调度策略业务逻辑错误: {str(e)}")
        raise HTTPException(status_code=500, detail=str(e))
    except Exception as e:
        logger.error(f"执行调度策略未知错误: {str(e)}")
        raise HTTPException(status_code=500, detail=f"执行调度策略失败: {str(e)}")


@router.get("/statistics", response_model=DataResponse[Dict[str, Any]], summary="获取调度策略统计信息")
async def get_statistics(
    db: Session = Depends(get_db)
):
    """
    获取调度策略统计信息
    
    包括总数、按状态分组、按类型分组、按场景分组的统计
    """
    try:
        service = SchedulingService(db)
        stats = service.get_strategy_statistics()
        
        logger.info("获取调度策略统计信息成功")
        
        return DataResponse(
            success=True,
            message="获取调度策略统计信息成功",
            data=stats
        )
        
    except BaseCustomException as e:
        logger.error(f"获取调度策略统计信息业务逻辑错误: {str(e)}")
        raise HTTPException(status_code=500, detail=str(e))
    except Exception as e:
        logger.error(f"获取调度策略统计信息未知错误: {str(e)}")
        raise HTTPException(status_code=500, detail=f"获取调度策略统计信息失败: {str(e)}")


@router.patch("/strategies/{strategy_id}/status", response_model=DataResponse[SchedulingStrategyResponse], summary="更新调度策略状态")
async def update_strategy_status(
    new_status: str = Query(..., description="新状态 (draft, active, paused, deprecated)"),
    strategy_id: str = Path(..., description="策略ID"),
    db: Session = Depends(get_db)
):
    """
    快速更新调度策略状态
    """
    try:
        service = SchedulingService(db)
        
        # 验证状态值
        valid_statuses = ["draft", "active", "paused", "deprecated"]
        if new_status not in valid_statuses:
            raise ValidationException(f"无效的状态值，必须是以下之一: {valid_statuses}")
        
        update_data = SchedulingStrategyUpdate(status=new_status)
        strategy = service.update_strategy(strategy_id, update_data)
        
        logger.info(f"更新调度策略状态成功: {strategy_id} -> {new_status}")
        
        return DataResponse(
            success=True,
            message=f"调度策略状态更新为 '{new_status}' 成功",
            data=strategy
        )
        
    except NotFoundException as e:
        logger.warning(f"调度策略不存在: {strategy_id}")
        raise HTTPException(status_code=404, detail=str(e))
    except ValidationException as e:
        logger.warning(f"更新调度策略状态验证失败: {str(e)}")
        raise HTTPException(status_code=422, detail=str(e))
    except BaseCustomException as e:
        logger.error(f"更新调度策略状态业务逻辑错误: {str(e)}")
        raise HTTPException(status_code=500, detail=str(e))
    except Exception as e:
        logger.error(f"更新调度策略状态未知错误: {str(e)}")
        raise HTTPException(status_code=500, detail=f"更新调度策略状态失败: {str(e)}") 